import store from '@/stores';
import router from '@/router';
import Vue from 'vue';

/**
 * 读取tab
 * @param {[String]} id 可选，页签名称
 * @return {Array||Object} tab数组||单个页签的数据对象
 * @example this.$mytab.get()// 获取到所有tab记录，数组
 * @example this.$mytab.get('abc')// 获取到单个tab的数据，对象
 */
let get = function(id) {
    let data = store.state.mytab.mytab;
    if (id) {
        data = objInclude({ id: id }, data);
    }
    return data;
};
/**
 * 更新或添加tab
 * 逻辑
 *  - 如果已存在则更新
 *  - 如果不存在
 *    1. 如果是同一类型则添加在当前路由后面
 *    2. 如果不是同一类型则添加到同一类型标签后面
 *    3. 如果没有同一类型，则添加在最后面
 * @param {String} obj tab名称
 * @param {Object} value tab数据
 * @example this.$mytab.set(obj, value)// 设置tab，【遇到重复名称时覆盖】
 * @config nameRule 规则解释：{{_.Receipt}}+123456 双大括号包起来的代表需要国际化的，没有国际化的直接写，两个国际化单词或者国际化和普通单词拼接的地方用“+”链接
 */
let set = function(obj, value) {
    // 处理前先深拷贝
    let lishiData = JSON.parse(JSON.stringify(get()));
    let newObj = JSON.parse(JSON.stringify(value));
    newObj.id = obj;

    // 这个延迟操作纯属无奈，不应该这样做，但隐藏动作出发不正确，只能暂时这么处理了
    setTimeout(() => {
        // 触发页签隐藏动作回调
        let oldRoute = store.state.route.from;
        let oldID = oldRoute.name + oldRoute.path;
        if (objInclude({ id: oldID }, lishiData)) {
            // console.log('MyTabHide:', oldID)
            Vue.bus.$emit('hide' + oldID);
        }
    }, 200);

    // 显示页签处理
    let oldData = objInclude(newObj, lishiData);
    if (oldData) {
        // 已存在则更新
        oldData.name = newObj.name;
        oldData.path = newObj.path;
        // 触发页签新建动作回调
        Vue.bus.$emit('show' + obj);
    } else {
        let lastTabIndex = -1;
        let lastTab = lishiData.find((item, index) => {
            lastTabIndex = index;
            return item.path === store.state.route.from.fullPath;
        });
        if (lastTab && lastTab.model === newObj.model) {
            lishiData.splice(lastTabIndex + 1, 0, newObj);
        } else {
            lishiData.push(newObj);
        }
        // if (currentTab && currentTab.model === newObj.model) {

        // }
    }
    store.dispatch('mytab/update_mytab', lishiData);

    if (lishiData.length > 1) {
        store.dispatch('layout/update_sideFull', false);
    }

    // 保存tab到localStore
    saveTabToLocalStore();
};

/**
 * 删除页签
 * 逻辑
 *  - 如果关闭的非当前激活页签，则直接删除页签
 *  - 如果关闭的是当前激活页签
 *    1. 如果关闭的页签前面那为同一类型, 关闭并跳转前一页签
 *    2. 如果关闭的页签后面那为同一类型, 关闭并跳转前一页签
 *    3. 如果关闭的页签后没有为同一类型, 关闭并跳转前一页签
 * 删除页签的场景
 * 1. 页签上直接删除
 * 2. 新建完成后删除并跳转至编辑页面
 * 3. 编辑页面不存在的时候跳转至列表标签
 * @param  {String} id 页签名称
 * @example this.$mytab.del('1709130093')// 接受参数为页签名称的字符串，将会删掉页签
 */
let del = function(id) {
    if (typeof id !== 'string') {
        console.log('$mytab.del 参数必须为页签名称，且为字符串属性', id);
        return false;
    }
    if (id === 'home/') {
        console.log('工作台页签禁止删除！');
        return false;
    }

    // 处理前先深拷贝
    let lishiData = JSON.parse(JSON.stringify(get()));
    let currentTabIndex = -1;
    let currentTab = lishiData.find((item, index) => {
        currentTabIndex = index;
        return item.id === id;
    });
    let currentRouter = router.history.current;
    if (!currentTab) {
        console.log('$mytab.del 未找到该TAB', id);
    } else {
        // 如果关闭的是当前激活页签
        if (currentTab.path === currentRouter.path || currentTab.path === currentRouter.fullPath) {
            if (lishiData[currentTabIndex - 1] && lishiData[currentTabIndex - 1].model === currentTab.model) {
                router.replace(lishiData[currentTabIndex - 1].path);
            } else if (lishiData[currentTabIndex + 1] && lishiData[currentTabIndex + 1].model === currentTab.model) {
                router.replace(lishiData[currentTabIndex + 1].path);
            } else {
                router.replace(lishiData[currentTabIndex - 1].path);
            }
        }
        lishiData.splice(currentTabIndex, 1);
        store.dispatch('mytab/update_mytab', lishiData);
    }

    // 触发页签关闭动作回调
    Vue.bus.$emit('close' + id);

    // 保存tab到localStore
    saveTabToLocalStore();
};

// 按照存储的规则重置页签名称
let resetName = function() {
    let tabs = JSON.parse(JSON.stringify(get()));
    // 更新mytab状态
    store.dispatch('mytab/update_mytab', tabs);
};

/**
 * 注册打开页签事件【由无到有】
 * @param {String} id myTab ID，由this.$route.name + this.$route.path组成
 * @example this.$mytab.onOpen(mytabID, () => {
            console.log('on 页签被创建', this.tab.name)
        })
 * 必须出现在 $mytab.set 方法之前
 * 可多次使用，但最后一次会覆盖前面所有【事件句柄仅执行一次】
 */
let onOpen = function(id, fn) {
    Vue.bus.$off('open' + id);
    Vue.bus.$on('open' + id, () => {
        fn(id);
    });
};
/**
 * 注册显示页签事件【由隐藏状态到显示】
 * @param {String} id myTab ID，由this.$route.name + this.$route.path组成
 * @example this.$mytab.onShow(mytabID, () => {
            console.log('show 页签被显示', this.tab.name)
        })
 * 必须出现在 $mytab.set 方法之前
 * 可多次使用，但最后一次会覆盖前面所有【事件句柄仅执行一次】
 */
let onShow = function(id, fn) {
    Vue.bus.$off('show' + id);
    Vue.bus.$on('show' + id, () => {
        fn(id);
    });
};
/**
 * 注册隐藏页签事件
 * @param {String} id myTab ID，由this.$route.name + this.$route.path组成
 * @example this.$mytab.onHide(mytabID, () => {
            console.log('hide 页签被隐藏', this.tab.name)
        })
 * 必须出现在 $mytab.set 方法之前
 * 可多次使用，但最后一次会覆盖前面所有【事件句柄仅执行一次】
 */
let onHide = function(id, fn) {
    Vue.bus.$off('hide' + id);
    Vue.bus.$on('hide' + id, () => {
        fn(id);
    });
};
/**
 * 注册关闭页签事件
 * @param {String} id myTab ID，由this.$route.name + this.$route.path组成
 * @example this.$mytab.onClose(mytabID, () => {
            console.log('close 页签被关闭', this.tab.name)
        })
 * 必须出现在 $mytab.set 方法之前
 * 可多次使用，但最后一次会覆盖前面所有【事件句柄仅执行一次】
 */
let onClose = function(id, fn) {
    Vue.bus.$off('close' + id);
    Vue.bus.$on('close' + id, () => {
        fn(id);
    });
};

/**
 * 检查数组中是否包含该元素，数组元素是对象，以id值为基准检查
 * @param  {Object} child 要检查的对象
 * @param  {Object} pater 对象集合的数组
 * @return {Object||Boolean}       存在时返回集合的索引，不存在时返回false
 */
function objInclude(child, pater) {
    // let pater = get()
    let id = child.id;
    let reObj = false;
    pater.map(v => {
        if (v.id === id) {
            reObj = v;
        }
    });

    return reObj;
}

function saveTabToLocalStore() {
    Vue.localStore.set('myTab', JSON.stringify(get()));
}

export default {
    get,
    set,
    del,
    resetName,
    onOpen,
    onShow,
    onHide,
    onClose
};
